package com.aisino.encrypt.algorithm;

import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import com.aisino.encrypt.entity.EncryptKey;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.util.Base64;

/**
 * @author Jeffery
 * @date 2021-09-27 12:02
 * 国密sm2算法
 */
public class SM2Util {

    /**
     * 签名
     *
     * @param privateKey 私钥
     * @param publicKey  公钥
     * @param sourceStr  文本
     * @return 签名
     */
    public static byte[] sign(byte[] privateKey, byte[] publicKey, String sourceStr) throws UnsupportedEncodingException {
        final SM2 sm2 = new SM2(privateKey, publicKey);
        // 公钥加密，私钥解密
        byte[] sign = sm2.sign(sourceStr.getBytes("utf-8"));
        return sign;
    }

    /**
     * 生成公钥私钥
     *
     * @return
     */
    public static EncryptKey getEncryptKey() {
        String privateKey = null, publicKey = null;
        try {
            KeyPair pair = SecureUtil.generateKeyPair("SM2");
            byte[] privateKeyByte = pair.getPrivate().getEncoded();
            byte[] publicKeyByte = pair.getPublic().getEncoded();
            privateKey = Base64.getEncoder().encodeToString(privateKeyByte);
            publicKey = Base64.getEncoder().encodeToString(publicKeyByte);
        } catch (Exception e) {
            System.out.println("生成密钥异常：" + e.getMessage());
            return null;
        }
        return new EncryptKey(privateKey, publicKey);
    }

    /**
     * 解密
     *
     * @param privateKey 私钥
     * @param publicKey  公钥
     * @param encryptStr 明文字符串
     * @return
     */
    public static String decrypt(String privateKey, String publicKey, String encryptStr) {
        SM2 sm2 = SmUtil.sm2(privateKey, publicKey);
        String decryptStr = StrUtil.utf8Str(sm2.decryptFromBcd(encryptStr, KeyType.PrivateKey));
        return decryptStr;
    }

    /**
     * 加密
     *
     * @param privateKey 私钥
     * @param publicKey  公钥
     * @param sourceStr  明文字符串
     * @return
     */
    public static String encrypt(String privateKey, String publicKey, String sourceStr) {
        SM2 sm2 = SmUtil.sm2(privateKey, publicKey);
        // 公钥加密，私钥解密
        String encryptStr = sm2.encryptBcd(sourceStr, KeyType.PublicKey);
        return encryptStr;
    }


    public static void main(String[] args) throws UnsupportedEncodingException {
        TimeInterval timer = new TimeInterval();
        /*EncryptKey key = getEncryptKey();
        log.info("生成密钥耗时：{}", timer.interval());
        log.info("私钥：{}", key.getPrivateKeyStr());
        log.info("公钥：{}", key.getPublicKeyStr());*/
        timer.start("1");
        String privateKey = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgX2a4nRamW+lG/GaNQPI2bbtxo7LwoXIsHesDJCc4jL2gCgYIKoEcz1UBgi2hRANCAARK15AqMTxSBHvVF444zWXPQOv4HlWEzmucg7ay/23iV1jhokygF7SSNdd8c3RRl31eU00mcRxf8cniiiRt7GBr";
        String publicKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAESteQKjE8UgR71ReOOM1lz0Dr+B5VhM5rnIO2sv9t4ldY4aJMoBe0kjXXfHN0UZd9XlNNJnEcX/HJ4ookbexgaw==";
        String encryptStr = encrypt(privateKey, publicKey, "1111");
        System.out.println("耗时" + timer.intervalMs("1") + "毫秒。加密字符串：" + encryptStr);
        timer.start("2");
        String decryptStr = decrypt(privateKey, publicKey, encryptStr);
        System.out.println("耗时" + timer.intervalMs("2") + "毫秒。解密字符串：" + decryptStr);

        String encryptByte = new String(sign(Base64.getDecoder().decode(privateKey), Base64.getDecoder().decode(publicKey), encryptStr));
        System.out.println(encryptByte);
    }

}
